########################################################################
#  Pyfm - personal finance data-base
#  Copyright (C) 2007,8 Ehud Ben-Reuven
#  udi@benreuven.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
########################################################################
"""This is a wrapper that add import commands."""
import os
from obj.mycmd import MyCmd
from obj.flat import stagvalue
from lib import dirs
import logging

import ofx2flt, ofx22flt
import directnet_checking
import bll_checking, bll_portfolio_position, bll_portfolio_activity
import citina_portfolio_position, citina_portfolio_activity
import gnucash
import soi

class MyCmdImports(MyCmd):
	modules={
		'ofx':ofx2flt,
		'ofx2':ofx22flt,
		'dnc':directnet_checking,
		'bllc':bll_checking,
		'bllpp':bll_portfolio_position,
		'bllpa':bll_portfolio_activity,		
		'citipp':citina_portfolio_position,
		'citipa':citina_portfolio_activity,
		'gnucash':gnucash,
		'soi':soi,
		}
	def do_import(self,line):
		"""Import files into flat files. The general command structure is:
	import S=<source> [FILE=<path>] [-FORCE] [<additioal-flat-line>]
The source specify what is the source of information being imported.
If you don't specify it, you will get a list of all available sources.
To get help information on a specific source, type:
	import S=<source> -HELP
	
The files of each source should be placed in an appropriate sub-folder 
below $PYFM_DATA/imports/ and have an appropriate file extension
(*.csv, *.ofx, *.qfx, *.xls)
See the specific help of each source for more information.
You can override this with the FILE=<path>
Where <path> can be an individual file or a directory from which 
all sub-directories will be scanned for files. You can also use '*'
in the path and you can specificy multiple paths by using multiple
FILE=<path> pairs.

The files are converted to flat file(s) at an appropriate subdirectory
below $PYFM_DATA/flt/
conversions are not perfromed if the flat files already exists
unless you specify -FORCE=1 to force the convertion.

Importing from some sources requires two step converion:
The first step generates a file at $PYFM_DATA/temp/ directory
which is then converted to the flat file. The first convertion is
performed only if the flat file and the temp/ file do not exist
or if you use -FORCE.

Some sources may look for additional paramaters in
<additional-flat-line>, for example CURRENCY=XXX
See individual help.
The <additional-flat-line> may also include additional tag-value pairs
that are duplicated, as-is, in every flat line being created by the command.
For example:
FILE=<file> - you need to specify this only if you want to override the
	default which is the name of the flat file itself.
ACCTID=<acctid> - Use this if you know that all lines in the imported document
	relates to the same account. In many cases this is not true or not needed since
	account information already exists in the imported document.
ACCTGRP=<acctgrp> - Use this if you know that all information in the
	imported file relates to a specific group of accounts. In many cases
	this is not needed because you already have the account identified
	in each line and somewhere else in your flat-line data-base you have
	specificed the grouping of this account. Using this option may generate
	inappropriate grouping of all accounts appearing in the statement which 
	may be different from the grouping you intended. The best solution will be
	use a different group-name (and to use the fact that an account can belong
	to more than one group.)
"""
		s=line.pop('S',None)
		if not s:
			sources=self.modules.keys()
			sources.sort()
			for s in sources: print s,
			print
			return
		elif len(s)==1 and s[0]=='*':
			s=self.modules.keys()
		
		help = line.pop('-HELP',None)!=None
		force = line.pop('-FORCE',None)!=None
		original_line=line

		for s1 in s:
			module=self.modules[s1]
			if help:
				print module.help
				continue
			
			line=original_line.copy()
	
			if hasattr(module, 'path') and callable(module.path):
				path=module.path(line) # The module's path method can eat up parameters from the line
			fnames=dirs.globLine(line, dirs.imports(path+[module.ext])) # pops FILE so do it before linetxt
			
			linetxt=[]
			for tag in line:
				linetxt.append(stagvalue(tag,line[tag]))
			linetxt = ' '.join(linetxt)
	
			for fname in fnames:
				name=dirs.name(fname)
				# build output file name
				flatname=dirs.flt(path+[name+'.txt'])
				# Check if it was already computed
				if not force and os.access(flatname,os.F_OK): continue
				print fname+'->'+flatname
				
				# Convert to temp file.
				if hasattr(module, 'pre') and callable(module.pre):
					tmpfile=dirs.temp(name+'.tmp')
					# If the requested flat file already exists dont to anything
					if force or not os.access(tmpfile,os.F_OK):
						logging.info('%s','converting to temp file')
						if os.access(tmpfile,os.F_OK):
							os.remove(tmpfile)
						module.pre(fname,tmpfile)
					fname=tmpfile
					
				try:
					fout = open(flatname,'w')
					module.flat(fname,fout,linetxt)
					fout.close()
				except IOError, e:
					print "Error converting %s to flatfile %s: %s" % (fname, flatname, e)
					fout.close()

